#ifndef CONTROL_H
#define CONTROL_H

#include "MsgTrans.h"
#include "Wimp.h"

/* Parses control file and builds data structures of what to install.
   Functions include error reporting where appropriate and also indicate
   errors in their return values. */

/* MessageTrans control block and parameters */
typedef struct {
  msgtrans_filedesc *fd;
  char *param[4];
} control_msgtrans_data;

control_msgtrans_data *control_msgtrans_data_new(const char *filename);

/* Returns looked up message in malloc block; see msgtransdyn for report */
char *control_msgtrans_lookup(const control_msgtrans_data *, const char *token,
                              BOOL report);

/* Splices a token's base name with an item number;
   result gets overwritten on next call
 */
const char *control_splice_token(const char *base, int num);



/* Item's status wrt being optional */
typedef enum {
  control_OptionalPrune,  /* Not to be installed */
  control_NotOptional,
  control_OptionalOn,     /* On by default or at user's behest */
  control_OptionalOff     /* Off   "      */
} control_optional_t;


typedef struct {
  char *name;          /* Leafname of archive in Items subdirectory */
  char *location_leaf; /* Appended to location directory */
  int disc;            /* Disc item is on */
  int location;        /* Location to be installed at */
  control_optional_t optional;
  char *desc;          /* Interactive help description for optional items */
  char *icon;          /* Shown while item is being installed */
  char *script;        /* To be called after unpacking, or NULL */
  icon_handle opt_icon;/* For option button */
} control_item;


control_item *control_item_new(void);

void control_item_delete(control_item *);

BOOL control_item_lookup(control_item *, int item_num,
                         const control_msgtrans_data *);
/* Returns FALSE if any lookups fail */

control_item *control_item_new_and_lookup(int item_num,
                                          const control_msgtrans_data *);

/* Returns how many installation stages this item has:
   copy, decompress, extract, script */
int control_item_count_stages(const control_item *);



typedef struct {
  char *icon;          /* Draggable icon sprite name */
  char *prompt;        /* Message to show user to ask them to drag */
  char *pathname;
  char *leafname;
  control_optional_t optional;    /* Not implemented */
} control_location;


control_location *control_location_new(void);

void control_location_delete(control_location *);

BOOL control_location_lookup(control_location *, int location_num,
                             const control_msgtrans_data *);
/* Returns FALSE if any lookups fail */

control_location *control_location_new_and_lookup(int location_num,
                                                  const control_msgtrans_data*);



typedef struct {
  char *human_name;
  int num_items;        /* Number of items belonging to this disc */
  control_item **items; /* Vector of items */
  int installed_items;  /* Number of items that have been installed */
  int num_stages;       /* How many installation stages are on this disc */
  int installed_stages; /* and how many have been installed so far */
} control_disc;


control_disc *control_disc_new(void);

void control_disc_delete(control_disc *);

BOOL control_disc_lookup(control_disc *, int disc_num,
                         const control_msgtrans_data *);
/* Returns FALSE if any lookups fail */

control_disc *control_disc_new_and_lookup(int disc_num,
                                          const control_msgtrans_data *);

/* This enumerates items and fills in num_stages;
   disc_num is only needed for logging */
int control_disc_count_stages(control_disc *, int disc_num);



/* Master data */
typedef struct {
  control_msgtrans_data *msgs;
  int num_items;
  control_item **items;
  int num_locations;
  control_location **locations;
  int installed_locations;
  int num_discs;
  control_disc **discs;
  int installed_discs; /* Number of discs that have been installed */
  const char *master_location_dir; /* First valid location is used to
                                      hold scripts etc */
  int num_stages;       /* How many installation stages there are */
  int installed_stages; /* and how many have been installed so far */
  BOOL reboot;          /* Whether to prompt for reboot when finished */
} control_master_data;


control_master_data *control_master_data_new(void);

/* Master data doesn't get deleted */

/* Also initialises install parameters */
BOOL control_master_data_open_control_file(control_master_data *,
                                           const char *control_filename);

/* _open_control_file() must be called before any of these */
BOOL control_master_data_lookup_items(control_master_data *);

BOOL control_master_data_lookup_locations(control_master_data *);

BOOL control_master_data_lookup_discs(control_master_data *);

/* Calls all the above in turn */
BOOL control_master_data_lookup_all(control_master_data *);

/* Calls control_master_data_new, _open_control_file, _init_parameters
   and _lookup_all, returning NULL if any lookups fail */
control_master_data *control_master_data_new_with_lookup(const char *
                                                         control_filename);

/* Counts number of optional items */
int control_master_data_count_optional_items(const control_master_data *);

/* Returns the array index of the nth optional item (input and output both
   start from 0) */
int control_master_data_get_nth_optional_item(const control_master_data *, int);

/* If also_off, prune items that are control_OptionalOff as well as
   control_OptionalPrune */
void control_master_data_prune_items(control_master_data *, BOOL also_off);

/* Fills in discs' items vectors after optional items have been pruned;
   returns FALSE if any items have invalid discs or locations
 */
BOOL control_master_data_populate_disc_items(control_master_data *);

/* This may not be called until user has chosen locations */
BOOL control_master_data_lookup_master_location(control_master_data *);

/* This enumerates discs and fills in num_stages for each as well as master */
int control_master_data_count_stages(control_master_data *);

/* Access optional field for an item */
#define CONTROL_ITEM_OPTIONAL(cd, n) ((cd)->items[(n)]->optional)


/* Removes items with OptionalPrune (and optionally control_OptionalOff) status
   from control_item vector, updating num_items;
   not usually called externally, used by control_master_data_prune_items()
 */
void control_prune_items(int *num_items, control_item **, BOOL also_off);

#ifdef NSTALL_DEBUG
void control_enumerate(control_master_data *);
#else
#define control_enumerate(c)
#endif

#endif /* CONTROL_H */
